#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

#define BaseSize 4096
#define gCreater 1
#define gUser 2
const std::string pathname = "/home/lintianci";
const int proj_id = 0x66;

class shm
{
private:
    void GetCommanKey()
    {
        _key = ftok(pathname.c_str(), proj_id);
        if (_key < 0)
        {
            std::cerr << "获取失败" << std::endl;
            perror("ftok");
            return;
        }
        std::cerr << "获取key成功：" <<toHex()<< std::endl;
    }
    void ShmGetHelper(int flag)
    {
        
        _shmID = shmget(_key, BaseSize, flag);
        if(_shmID < 0){
            std::cerr << "获取失败,ID:" << _shmID<< std::endl;
            perror("shmget");
            return;
        }
        std::cerr << "获取id成功:"<<_shmID << std::endl;
    }
    void ShmDeleteHelper(){
        std::cerr << "进程:" << std::to_string(getpid()) << "返还id" << std::endl;
        int res = shmctl(_shmID, IPC_RMID, nullptr);
        if(res < 0){
            std::cerr << "返还失败" << std::endl;
            perror("shmctl");
            return;
        }
            std::cerr << "返还成功" << std::endl;
    }
    void GetUserShmCreate()
    {
        std::cerr << "进程:" << std::to_string(getpid()) << "获取id" << std::endl;
        ShmGetHelper( IPC_CREAT | 0666); //获取id
    }
    void GetCreaterShmCreate(){
        std::cerr << "进程:" << std::to_string(getpid()) << "获取id" << std::endl;
        ShmGetHelper(IPC_CREAT | IPC_EXCL | 0666);//创建id
    }
    //连接地址空间
    void ShmAtVisionAdrress(){
        _addshm = shmat(_shmID, nullptr, 0);
        if(_addshm == nullptr){
            std::cerr << "连接失败" << std::endl;
            perror("shmat");
        }
        else
            std::cerr << "连接成功" << std::endl;
    }
    std::string toHex(){
        char buffer[128];
        snprintf(buffer, sizeof(buffer), "0x%x", _key);
        return std::string(buffer);
    }

public:
    shm(int who,const std::string& path = pathname,int pro_id = proj_id)
        : _who(who)
        ,_pathname(path)
        ,_proj_id(pro_id)
    {   
        std::cerr << "获取key" << std::endl;
        GetCommanKey();


        if(_who == gCreater){
            GetCreaterShmCreate();
        }
        else if(_who == gUser){
            GetUserShmCreate();
        }


        std::cerr << "进程:" << std::to_string(getpid()) << "连接共享内存" << std:: endl;
        ShmAtVisionAdrress();
    }
    ~shm()
    {
        if(_who == gCreater && _key > 0){
            ShmDeleteHelper();
        }
    }
    void* Addr(){
        return _addshm;
    }

private:
    int _key;
    int _shmID;
    
    int _who;
    void *_addshm;

    int _proj_id;//获取key编码
    const std::string _pathname;//获取key路径
};


